package com.feinno.urcs.group.http.handler;

import com.feinno.urcs.group.GroupConfiguration;
import com.feinno.urcs.group.GroupConstants;
import com.feinno.urcs.group.GroupError;
import com.feinno.urcs.group.GroupException;
import com.feinno.urcs.group.entity.CreateGroupArgs;
import com.feinno.urcs.group.entity.GroupInfo;
import com.feinno.urcs.group.entity.GroupMember;
import com.feinno.urcs.group.entity.GroupMemberStatus;
import com.feinno.urcs.group.http.servlet.BaseHttpServlet;
import com.feinno.urcs.group.http.servlet.GroupHttpContext;
import com.feinno.urcs.group.http.util.HttpHelper;
import com.feinno.urcs.group.http.util.StringHelper;
import com.feinno.urcs.group.pd.upstream.entity.*;
import com.feinno.urcs.nai.IMPU;
import com.feinno.urcs.profile.entity.ClientType;
import com.feinno.urcs.sip.UrcsSipFactory;
import com.feinno.urcs.types.MobileNo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sip.address.SipURI;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by wuzhiguo on 15-5-11.
 */
public class CreateGroupHandler extends BaseHttpServlet {

    private static final Logger LOGGER = LoggerFactory.getLogger(CreateGroupHandler.class);

    @Override
    public void process(final GroupHttpContext ctx) throws IOException {
        try {
            if (LOGGER.isInfoEnabled()) {
                String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
                LOGGER.info(String.format("Received Request: %s", requestString));
            }

            CreateGroupArgs createGroupArgs = buildCreateGroupReq(ctx);
            createGroupArgs.setClientType(ClientType.PC);
            if (createGroupArgs == null) {
                String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
                LOGGER.error(String.format("buildCreateGroupReq Failed. Received Request: %s", requestString));
                ctx.getResponse().sendError(400, "ArgsError");
                return;
            }

            // 调用GroupService
            GroupInfo groupInfo = ctx.getGroupService().checkAndCreate(createGroupArgs);

            byte[] responseBody = buildResponseBody(groupInfo);
            ctx.getResponse().setStatus(201);
            setDigestAuthenticationInfo(ctx);
            ctx.getResponse().setContentType("application/public-group+xml; charset=\"utf-8\"");
            ctx.getResponse().setContentLength(responseBody.length);
            ctx.getResponse().setHeader("ETag", "0");
            ctx.getResponse().getOutputStream().write(responseBody);
            ctx.getResponse().getOutputStream().flush();

            if (LOGGER.isInfoEnabled()) {
                String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
                String responseBodyString = new String(responseBody);
                LOGGER.info(String.format("process() Successfully.\n"
                                + "Received Request: %s\n"
                                + "Send Response Body: %s",
                        requestString,
                        responseBodyString));
            }

            // inviteMembers
            List<MobileNo> inviteList = createGroupArgs.getMembers();
            MobileNo[] members = new MobileNo[inviteList.size()];
            inviteList.toArray(members);
            ctx.getGroupService().inviteGroupMembers(groupInfo.getGroupIndex(), createGroupArgs.getFromMobileNo(), members);
        } catch (GroupException gex) {
            GroupError error = gex.getError();
            String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
            LOGGER.error(String.format("process() GroupException. GroupError Code: %s Received Request: %s",
                    error.getSipCode(), requestString), gex);
            ctx.getResponse().sendError(error.getSipCode(), "GroupError");
        } catch (Exception ex) {
            String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
            LOGGER.error(String.format("process() Error. Received Request: %s", requestString), ex);
            ctx.getResponse().sendError(500, "ServerError");
        }
    }

    private CreateGroupArgs buildCreateGroupReq(GroupHttpContext ctx) {
        try {
            PublicGroup publicGroup = new PublicGroup();
            publicGroup.parseXmlFrom(ctx.getBodyString());
            if (publicGroup.getList() != null && !StringHelper.isNullOrEmpty(publicGroup.getList().getName())) {
                CreateGroupArgs createGroupArgs = new CreateGroupArgs();
                createGroupArgs.setFromMobileNo( MobileNo.parseFrom(ctx.getSenderIMPU().getUser()));
                createGroupArgs.setConversationId(StringHelper.generateUUIDString());
                createGroupArgs.setSubject(publicGroup.getList().getName());

                List<PublicGroup_List_Entry> entryList = publicGroup.getList().getEntryList();
                if (entryList != null && entryList.size() > 0) {
                    List<MobileNo> inviteList = new ArrayList<>();
                    for (int i = 0; i < entryList.size(); i++) {
                        PublicGroup_List_Entry entry = entryList.get(i);
                        if (!StringHelper.isNullOrEmpty(entry.getUri())) {
                            IMPU item = IMPU.parse(entry.getUri());
                            inviteList.add( MobileNo.parseFrom(item.getUser()));
                        }
                    }
                    if (inviteList != null && inviteList.size() > 0) {
                        createGroupArgs.setMembers(inviteList);
                    }
                }

                return createGroupArgs;
            }

        } catch (Exception ex) {
            String requestString = HttpHelper.getRequestString(ctx.getRequest(), ctx.getBodyString());
            LOGGER.error(String.format("buildCreateGroupReq() Error. Received Request: %s", requestString), ex);
        }

        return null;
    }

    private byte[] buildResponseBody(GroupInfo groupInfo) throws Exception {
        String groupUri = groupInfo.getGroupIndex().getConferenceUri();
        MobileNo groupAdmin = groupInfo.getGroupAdmin();

        PublicGroup publicGroup = new PublicGroup();
        PublicGroup_List list = new PublicGroup_List();
        PublicGroup_MetaData metaData = new PublicGroup_MetaData();
        publicGroup.setList(list);
        publicGroup.setMetaData(metaData);

        list.setName(groupInfo.getSubject());
        list.setUri(groupUri);
        list.setMax(String.valueOf(groupInfo.getLimitMemberCount()));

        List<PublicGroup_List_Entry> entryList = new ArrayList<>();
        list.setEntryList(entryList);

        if (groupInfo.getMembers() != null && groupInfo.getMembers().size() > 0) {
            for (int i = 0; i < groupInfo.getMembers().size(); i++) {
                GroupMember member = groupInfo.getMembers().get(i);
                PublicGroup_List_Entry entry = new PublicGroup_List_Entry();
                entryList.add(entry);

                SipURI memberSipURL = UrcsSipFactory.getAddressFactory().createSipURI(member.getMobileNo().toString(), GroupConfiguration.INSTANCE.getDomain());
                entry.setUri(memberSipURL.toString());

                // 只有PENDING状态是等待同意，其他都是正式群成员
                if (member.getStatus() == GroupMemberStatus.PENDING) {
                    entryList.remove(entry);
                    continue;
//                    entry.setStatus("pending");
                } else {
                    entry.setStatus("active");
                }

                if (member.getMobileNo().equals(groupAdmin)) {
                    entry.setOwner("true");
                }

                entry.setDisplayName(new PublicGroup_List_Entry_DisplayName(member.getDisplayname()));
            }
        }

        SipURI creatorSipURL = UrcsSipFactory.getAddressFactory().createSipURI(groupAdmin.toString(), GroupConfiguration.INSTANCE.getDomain());
        metaData.setCreator(new PublicGroup_MetaData_Creator(creatorSipURL.toString()));
        metaData.setIdentifier(new PublicGroup_MetaData_Identifier(String.format(GroupConstants.PUBLIC_GROUP_IDENTIFIER_TEMPLATE, groupUri)));
        metaData.setTimestamp(new PublicGroup_MetaData_Timestamp(StringHelper.generateXmlDateFormatString(groupInfo.getCreateTime())));
        metaData.setNeedPermit(new PublicGroup_MetaData_NeedPermit("false"));

        return publicGroup.toXmlByteArray();
    }
}
